home *** CD-ROM | disk | FTP | other *** search
/ Hardcore Visual Basic 5.0 (2nd Edition) / Hardcore Visual Basic 5.0 - Second Edition (1997)(Microsoft Press).iso / Code / Bytes.bas < prev    next >
BASIC Source File  |  1997-06-14  |  13KB  |  427 lines

  1. Attribute VB_Name = "MBytes"
  2. Option Explicit
  3.  
  4. Public Enum EErrorBytes
  5.     eeBaseBytes = 13430     ' Bytes
  6. End Enum
  7.  
  8. Private aPower2(0 To 31) As Long
  9.  
  10. Sub StrToBytes(ab() As Byte, s As String)
  11.     If MUtility.IsArrayEmpty(ab) Then
  12.         ' Assign to empty array
  13.         ab = StrConv(s, vbFromUnicode)
  14.     Else
  15.         Dim cab As Long
  16.         ' Copy to existing array, padding or truncating if necessary
  17.         cab = UBound(ab) - LBound(ab) + 1
  18.         If Len(s) < cab Then s = s & String$(cab - Len(s), 0)
  19.         If UnicodeTypeLib Then
  20.             Dim st As String
  21.             st = StrConv(s, vbFromUnicode)
  22.             CopyMemoryStr ab(LBound(ab)), st, cab
  23.         Else
  24.             CopyMemoryStr ab(LBound(ab)), s, cab
  25.         End If
  26.     End If
  27. End Sub
  28.  
  29. Function StrToBytesV(s As String) As Variant
  30.     ' Copy to array
  31.     StrToBytesV = StrConv(s, vbFromUnicode)
  32. End Function
  33.  
  34. Function BytesToStr(ab() As Byte) As String
  35.     BytesToStr = StrConv(ab, vbUnicode)
  36. End Function
  37.  
  38. Function ByteZToStr(ab() As Byte) As String
  39.     If UnicodeTypeLib Then
  40.         ByteZToStr = ab
  41.     Else
  42.         ByteZToStr = StrConv(ab, vbUnicode)
  43.     End If
  44.     ByteZToStr = Left$(ByteZToStr, lstrlen(ByteZToStr))
  45. End Function
  46.  
  47. Function BytesToWord(abBuf() As Byte, iOffset As Long) As Integer
  48.     BugAssert iOffset <= UBound(abBuf) + 1 - 2
  49.     Dim w As Integer
  50.     CopyMemory w, abBuf(iOffset), 2
  51.     BytesToWord = w
  52. End Function
  53.  
  54. Function BytesToDWord(abBuf() As Byte, iOffset As Long) As Long
  55.     BugAssert iOffset <= UBound(abBuf) + 1 - 4
  56.     Dim dw As Long
  57.     CopyMemory dw, abBuf(iOffset), 4
  58.     BytesToDWord = dw
  59. End Function
  60.  
  61. Sub BytesFromWord(w As Integer, abBuf() As Byte, iOffset As Long)
  62.     BugAssert iOffset <= UBound(abBuf)
  63.     CopyMemory abBuf(iOffset), w, 2
  64. End Sub
  65.  
  66. ' Read string with length in first byte
  67. Function BytesToPStr(ab() As Byte, iOffset As Long) As String
  68.     BugAssert iOffset <= UBound(ab)
  69.     BytesToPStr = MidBytes(ab, iOffset + 1, ab(iOffset))
  70. End Function
  71.  
  72. Sub BytesFromDWord(dw As Long, abBuf() As Byte, iOffset As Long)
  73.     BugAssert iOffset <= UBound(abBuf) + 1 - 4
  74.     CopyMemory abBuf(iOffset), dw, 4
  75. End Sub
  76.  
  77. '' Emulate relevant Basic string functions for arrays of bytes:
  78. ''     Len$             LenBytes
  79. ''     Mid$ function    MidBytes
  80. ''     Mid$ statement   InsBytes sub
  81. ''     Left$            LeftBytes
  82. ''     Right$           RightBytes
  83.  
  84. ' LenBytes - Emulates Len for array of bytes
  85. Function LenBytes(ab() As Byte) As Long
  86.     LenBytes = UBound(ab) - LBound(ab) + 1
  87. End Function
  88.  
  89. ' MidBytes - emulates Mid$ function for array of bytes
  90. ' (Note that MidBytes does not emulate Mid$ exactly--string fields
  91. ' in byte arrays are often null-padded, and MidBytes can extract
  92. ' non-null portion)
  93. Function MidBytes(ab() As Byte, ByVal iOffset As Long, _
  94.                   Optional ByVal iLen As Long = 0, _
  95.                   Optional fToNull As Boolean = False) As String
  96.     BugAssert iOffset < LenBytes(ab) And iOffset >= 0
  97.     Dim s As String, cab As Long
  98.     ' Calculate length
  99.     If iLen <= 0 Then
  100.         cab = LenBytes(ab) - iOffset
  101.     Else
  102.         cab = iLen
  103.     End If
  104.     ' Assign and return string
  105.     s = String$(cab, 0)
  106.     CopyMemoryToStr s, ab(iOffset), cab
  107.     If UnicodeTypeLib Then s = MUtility.StrZToStr(StrConv(s, vbUnicode))
  108.     If fToNull Then
  109.         cab = InStr(s, vbNullChar)
  110.         If cab Then
  111.             MidBytes = Left$(s, cab - 1)
  112.         Else
  113.             MidBytes = s
  114.         End If
  115.     Else
  116.         MidBytes = s
  117.     End If
  118. End Function
  119.  
  120. ' InsBytes - Emulates Mid$ statement for array of bytes
  121. ' (Note that InsBytes does not emulate Mid$ exactly--it inserts
  122. ' a null-padded string into a fixed-size field in order to work
  123. ' better with common use of byte arrays.)
  124. Sub InsBytes(sIns As String, ab() As Byte, ByVal iOffset As Long, _
  125.              Optional iLen As Long = 0)
  126.     BugAssert iOffset < LenBytes(ab) And iOffset >= 0
  127.     Dim cab As Long
  128.     ' Calculate length
  129.     If iLen <= 0 Then
  130.         cab = Len(sIns)
  131.     Else
  132.         cab = iLen
  133.         ' Null-pad insertion string if too short
  134.         If (Len(sIns) < cab) Then
  135.             sIns = sIns & String$(cab - Len(sIns), 0)
  136.         End If
  137.     End If
  138.     BugAssert (Len(sIns) <= (LenBytes(ab) - iOffset))
  139.     ' Insert string
  140.     If UnicodeTypeLib Then
  141.         Dim s As String
  142.         s = StrConv(sIns, vbFromUnicode)
  143.         CopyMemoryStr ab(iOffset), s, cab
  144.     Else
  145.         CopyMemoryStr ab(iOffset), sIns, cab
  146.     End If
  147. End Sub
  148.  
  149. ' LeftBytes - Emulates Left$ function for array of bytes
  150. Function LeftBytes(ab() As Byte, ByVal iLen As Long) As String
  151.     Dim s As String
  152.     s = String$(iLen, 0)
  153.     CopyMemoryToStr s, ab(LBound(ab)), iLen
  154.     If UnicodeTypeLib Then s = MUtility.StrZToStr(StrConv(s, vbUnicode))
  155.     LeftBytes = s
  156. End Function
  157.  
  158. ' RightBytes - Emulates Right$ function for array of bytes
  159. Function RightBytes(ab() As Byte, ByVal iLen As Long) As String
  160.     Dim s As String
  161.     s = String$(iLen, 0)
  162.     CopyMemoryToStr s, ab(UBound(ab) - iLen + 1), iLen
  163.     If UnicodeTypeLib Then s = MUtility.StrZToStr(StrConv(s, vbUnicode))
  164.     RightBytes = s
  165. End Function
  166.  
  167. ' FillBytes - Fills field in array of bytes with given byte
  168. Sub FillBytes(ab() As Byte, ByVal b As Byte, _
  169.               ByVal iOffset As Long, ByVal iLen As Long)
  170.     BugAssert (iOffset < LenBytes(ab)) And (iOffset >= 0)
  171.     BugAssert iOffset - 1 + iLen <= LenBytes(ab)
  172.     Dim i As Long
  173.     For i = iOffset To iOffset + iLen - 1
  174.         ab(i) = b
  175.     Next
  176. End Sub
  177.  
  178. ' InStrBytes is not implemented because a simple version would
  179. ' simply be equivalent to InStr(ab(), s). This creates a temporary
  180. ' string for ab() on every call. An efficient version that works
  181. ' directly on arrays of bytes could be written in C.
  182.  
  183. Function LoWord(ByVal dw As Long) As Integer
  184.     If dw And &H8000& Then
  185.         LoWord = dw Or &HFFFF0000
  186.     Else
  187.         LoWord = dw And &HFFFF&
  188.     End If
  189. End Function
  190.  
  191. Function HiWord(ByVal dw As Long) As Integer
  192.     HiWord = (dw And &HFFFF0000) \ 65536
  193. End Function
  194.  
  195. Function LoByte(ByVal w As Integer) As Byte
  196.     LoByte = w And &HFF
  197. End Function
  198.  
  199. Function HiByte(ByVal w As Integer) As Byte
  200.     HiByte = (w And &HFF00&) \ 256
  201. End Function
  202.  
  203. Function MakeWord(ByVal bLo As Byte, ByVal bHi As Byte) As Integer
  204.     'CopyMemory MakeWord, bLo, 1
  205.     'CopyMemory ByVal VarPtr(MakeWord) + 1, bHi, 1
  206.     If bHi And &H80 Then
  207.         MakeWord = ((bHi * 256&) + bLo) Or &HFFFF0000
  208.     Else
  209.         MakeWord = (bHi * 256) + bLo
  210.     End If
  211. End Function
  212.  
  213. Function MakeDWord(ByVal wLo As Integer, ByVal wHi As Integer) As Long
  214.     'CopyMemory MakeDWord, wLo, 2
  215.     'CopyMemory ByVal VarPtr(MakeDWord) + 2, wHi, 2
  216.     MakeDWord = (wHi * 65536) + (wLo And &HFFFF&)
  217. End Function
  218.  
  219. Function LShiftWord(ByVal w As Integer, ByVal c As Integer) As Integer
  220.     BugAssert c >= 0 And c <= 15
  221.     Dim dw As Long
  222.     dw = w * Power2(c)
  223.     If dw And &H8000& Then
  224.         LShiftWord = CInt(dw And &H7FFF&) Or &H8000
  225.     Else
  226.         LShiftWord = dw And &HFFFF&
  227.     End If
  228. End Function
  229.  
  230. Function RShiftWord(ByVal w As Integer, ByVal c As Integer) As Integer
  231.     BugAssert c >= 0 And c <= 15
  232.     Dim dw As Long
  233.     If c = 0 Then
  234.         RShiftWord = w
  235.     Else
  236.         dw = w And &HFFFF&
  237.         dw = dw \ Power2(c)
  238.         RShiftWord = dw And &HFFFF&
  239.     End If
  240. End Function
  241.  
  242. Function LShiftDWord(ByVal dw As Long, ByVal c As Integer) As Long
  243.     BugAssert c >= 0 And c <= 31
  244.     Dim dwT As Long
  245.     On Error GoTo FailLShiftDWord
  246.     dwT = dw * Power2(c)
  247.     If dwT And &H80000000 Then
  248.         LShiftDWord = CLng(dwT And &H7FFFFFFF) Or &H80000000
  249.     Else
  250.         LShiftDWord = dwT
  251.     End If
  252.     Exit Function
  253. FailLShiftDWord:
  254.     LShiftDWord = &HFFFFFFFF
  255. End Function
  256.  
  257. Function RShiftDWord(ByVal dw As Long, ByVal c As Integer) As Long
  258.     BugAssert c >= 0 And c <= 31
  259.     On Error GoTo FailRShiftDWord
  260.     If c = 0 Then
  261.         RShiftDWord = dw
  262.     Else
  263.         RShiftDWord = dw \ Power2(c)
  264.     End If
  265.     Exit Function
  266. FailRShiftDWord:
  267.     RShiftDWord = 0
  268. End Function
  269.  
  270. ' Set or clear iBitPos bit in iValue according to whether
  271. ' iTest expression is true.
  272. Sub SetBitWord(ByVal iTest As Boolean, iValue As Integer, _
  273.                ByVal iBitPos As Integer)
  274.     BugAssert iBitPos >= 0 And iBitPos <= 15
  275.     If iTest Then
  276.         iValue = LoWord(iValue Or Power2(iBitPos))
  277.     Else
  278.         iValue = LoWord(iValue And Not Power2(iBitPos))
  279.     End If
  280. End Sub
  281.  
  282. Sub SetBitDWord(ByVal iTest As Boolean, iValue As Long, _
  283.                 ByVal iBitPos As Integer)
  284.     BugAssert iBitPos >= 0 And iBitPos <= 31
  285.     If iTest Then
  286.         iValue = iValue Or Power2(iBitPos)
  287.     Else
  288.         iValue = iValue And Not Power2(iBitPos)
  289.     End If
  290. End Sub
  291.  
  292. ' Get state of iBitPos bit in iValue
  293. Function GetBit(ByVal iValue As Long, ByVal iBitPos As Integer) As Boolean
  294.     BugAssert iBitPos >= 0 And iBitPos <= 31
  295.     GetBit = iValue And Power2(iBitPos)
  296. End Function
  297.  
  298. Function SwapWordBytes(ByVal w As Integer) As Integer
  299.     CopyMemory ByVal VarPtr(SwapWordBytes) + 1, w, 1
  300.     CopyMemory SwapWordBytes, ByVal VarPtr(w) + 1, 1
  301. End Function
  302.  
  303. Function SwapDWordWords(ByVal dw As Long) As Long
  304.     CopyMemory ByVal VarPtr(SwapDWordWords) + 2, dw, 2
  305.     CopyMemory SwapDWordWords, ByVal VarPtr(dw) + 2, 2
  306. End Function
  307.  
  308. ' Swap a little endian DWORD to big endian, or vice versa
  309. Function SwapEndian(ByVal dw As Long) As Long
  310.     CopyMemory ByVal VarPtr(SwapEndian) + 3, dw, 1
  311.     CopyMemory ByVal VarPtr(SwapEndian) + 2, ByVal VarPtr(dw) + 1, 1
  312.     CopyMemory ByVal VarPtr(SwapEndian) + 1, ByVal VarPtr(dw) + 2, 1
  313.     CopyMemory SwapEndian, ByVal VarPtr(dw) + 3, 1
  314. End Function
  315.  
  316. Function VBGetLogicalDrives() As String
  317.  
  318.     Dim f32  As Long, i As Integer, s As String
  319.     f32 = GetLogicalDrives()
  320.     For i = 0 To 25
  321.         s = s & IIf(f32 And 1, "+", "-")
  322.         f32 = MBytes.RShiftDWord(f32, 1)
  323.     Next
  324.     VBGetLogicalDrives = s
  325.     
  326. End Function
  327.  
  328. Property Get Power2(ByVal i As Integer) As Long
  329.     BugAssert i >= 0 And i <= 31
  330. #If fComponent = 0 Then
  331.     If aPower2(0) = 0 Then
  332.         aPower2(0) = &H1&
  333.         aPower2(1) = &H2&
  334.         aPower2(2) = &H4&
  335.         aPower2(3) = &H8&
  336.         aPower2(4) = &H10&
  337.         aPower2(5) = &H20&
  338.         aPower2(6) = &H40&
  339.         aPower2(7) = &H80&
  340.         aPower2(8) = &H100&
  341.         aPower2(9) = &H200&
  342.         aPower2(10) = &H400&
  343.         aPower2(11) = &H800&
  344.         aPower2(12) = &H1000&
  345.         aPower2(13) = &H2000&
  346.         aPower2(14) = &H4000&
  347.         aPower2(15) = &H8000&
  348.         aPower2(16) = &H10000
  349.         aPower2(17) = &H20000
  350.         aPower2(18) = &H40000
  351.         aPower2(19) = &H80000
  352.         aPower2(20) = &H100000
  353.         aPower2(21) = &H200000
  354.         aPower2(22) = &H400000
  355.         aPower2(23) = &H800000
  356.         aPower2(24) = &H1000000
  357.         aPower2(25) = &H2000000
  358.         aPower2(26) = &H4000000
  359.         aPower2(27) = &H8000000
  360.         aPower2(28) = &H10000000
  361.         aPower2(29) = &H20000000
  362.         aPower2(30) = &H40000000
  363.         aPower2(31) = &H80000000
  364.     End If
  365. #End If
  366.     Power2 = aPower2(i)
  367. End Property
  368.  
  369. #If fComponent Then
  370. Private Sub Class_Initialize()
  371.     aPower2(0) = &H1&
  372.     aPower2(1) = &H2&
  373.     aPower2(2) = &H4&
  374.     aPower2(3) = &H8&
  375.     aPower2(4) = &H10&
  376.     aPower2(5) = &H20&
  377.     aPower2(6) = &H40&
  378.     aPower2(7) = &H80&
  379.     aPower2(8) = &H100&
  380.     aPower2(9) = &H200&
  381.     aPower2(10) = &H400&
  382.     aPower2(11) = &H800&
  383.     aPower2(12) = &H1000&
  384.     aPower2(13) = &H2000&
  385.     aPower2(14) = &H4000&
  386.     aPower2(15) = &H8000&
  387.     aPower2(16) = &H10000
  388.     aPower2(17) = &H20000
  389.     aPower2(18) = &H40000
  390.     aPower2(19) = &H80000
  391.     aPower2(20) = &H100000
  392.     aPower2(21) = &H200000
  393.     aPower2(22) = &H400000
  394.     aPower2(23) = &H800000
  395.     aPower2(24) = &H1000000
  396.     aPower2(25) = &H2000000
  397.     aPower2(26) = &H4000000
  398.     aPower2(27) = &H8000000
  399.     aPower2(28) = &H10000000
  400.     aPower2(29) = &H20000000
  401.     aPower2(30) = &H40000000
  402.     aPower2(31) = &H80000000
  403. End Sub
  404. #End If
  405. '
  406.  
  407. #If fComponent = 0 Then
  408. Private Sub ErrRaise(e As Long)
  409.     Dim sText As String, sSource As String
  410.     If e > 1000 Then
  411.         sSource = App.ExeName & ".Bytes"
  412.         Select Case e
  413.         Case eeBaseBytes
  414.             BugAssert True
  415.        ' Case ee...
  416.        '     Add additional errors
  417.         End Select
  418.         Err.Raise COMError(e), sSource, sText
  419.     Else
  420.         ' Raise standard Visual Basic error
  421.         sSource = App.ExeName & ".VBError"
  422.         Err.Raise e, sSource
  423.     End If
  424. End Sub
  425. #End If
  426.  
  427.